package token

import (
	"fmt"
	"github.com/dgrijalva/jwt-go"
	"github.com/gin-gonic/gin"
	"net/http"
	"strings"
	"time"
)

// Hash消息认证签名实现token
type HmacUser struct {
	UserId   string `json:"user_id"` //根据用户id生成token
	UserName string `json:"user_name"`
}
type MyClaims struct {
	UserId string
	jwt.StandardClaims
}

var jwtKey = []byte("secret_renxing_csdn_gin") //证书签名秘钥，用来签发证书

func HmacCreateToken(c *gin.Context) {
	var user HmacUser
	c.Bind(&user) //绑定客户端传来的参数
	fmt.Println("user", user)
	if user.UserId == "" {
		c.JSON(http.StatusBadRequest, "user_id不能为空")
		return
	}
	token, err := _createToken(user)
	if err != nil {
		c.JSON(http.StatusInternalServerError, err)
		return
	}
	c.JSON(http.StatusOK, gin.H{
		"code": http.StatusOK,
		"msg":  "token创建成功",
		"data": gin.H{
			"user_id": user.UserId,
			"token":   token,
		},
	})
}

// 创建token
func _createToken(user HmacUser) (string, error) {
	expirationTime := time.Now().Add(7 * 24 * time.Hour) //token有效期截止时间，从当前时间往后7天
	claims := &MyClaims{
		UserId: user.UserId,
		StandardClaims: jwt.StandardClaims{
			ExpiresAt: expirationTime.Unix(),    //过期时间
			IssuedAt:  time.Now().Unix(),        //发布时间
			Subject:   "create hmac token demo", //主题
			Issuer:    "renxing",                //发布者
		},
	}
	token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims) //生成token
	tokenString, err := token.SignedString(jwtKey)
	if err != nil {
		return "", err
	}
	return tokenString, nil
}

// 校验token
func HmacAuthMiddleware() gin.HandlerFunc {
	return func(c *gin.Context) {
		auth := "renxing"
		// 获取authorization header
		Authorization := c.GetHeader("Authorization") //客户端传递的header信息，header的key是Authorization
		fmt.Println("header:Authorization", Authorization)
		if Authorization == "" || !strings.HasPrefix(Authorization, auth+":") { //验证token不为空，并且以 renxing: 为前缀
			c.JSON(http.StatusUnauthorized, gin.H{"code": http.StatusUnauthorized, "msg": "解析token前缀错误"})
			c.Abort()
			return
		}
		index := strings.Index(Authorization, auth+":") //找到token前缀对应的位置
		//真实token的值
		tokenString := Authorization[index+len(auth)+1:] //截取真实的token（开始位置为：索引开始的位置+关键字符的长度+1(:的长度为1)）
		fmt.Println("tokenString", tokenString)

		//解析token
		token, claims, err := _hamcParseToke(tokenString)
		//fmt.Println("token", token)
		//fmt.Println("claims", claims)
		if err != nil || !token.Valid { //解析错误或者过期等
			fmt.Println("err", err)
			c.JSON(http.StatusUnauthorized, gin.H{"code": http.StatusUnauthorized, "msg": "证书无效"})
			c.Abort()
			return
		}

		//校验比对解析后的token中的user_id是否和客户端传来的user_id匹配
		var user HmacUser
		c.Bind(&user)
		fmt.Println("claims_user_id", claims.UserId)
		if user.UserId != claims.UserId {
			c.JSON(http.StatusUnauthorized, gin.H{"code": http.StatusUnauthorized, "msg": "用户不存在"})
			c.Abort()
			return
		}
		c.Next()
	}
}

// 解析token
func _hamcParseToke(tokenString string) (*jwt.Token, *MyClaims, error) {
	claims := &MyClaims{}
	token, err := jwt.ParseWithClaims(tokenString, claims, func(token *jwt.Token) (i interface{}, err error) {
		return jwtKey, nil
	})
	return token, claims, err
}
